/******************************************************************************
 * File: usb_logger.c
 *
 * Description: This file is the USB Vendor Specific Device (VSD) Layer.
 *	The VSD defines 4 data pipes on EP1, EP2, EP3, EP4.
 *		EP1 is an OUT data pipe.
 *		EP2 is an  IN data pipe.
 *		EP3 is an OUT data pipe.
 *		EP4 is an  IN data pipe.
 *
 *	This file provides functions for:
 *		Initialising the device - USB_Class_LOGGER_Init(void)
 *		Initialising the 4 endpoints - USB_Class_Logger_Event()
 *		Initiating data transmission on EP2 - USB_Class_EP2_Send_Data()
 *		Initiating data transmission on EP4 - USB_Class_EP4_Send_Data()
 *		Receiving data on EP1 - USB_EP1_SERVICE_CALL()
 *		Receiving data on EP3 - USB_EP3_SERVICE_CALL()
 *
 ******************************************************************************/

/******************************************************************************
 * Includes
 *****************************************************************************/
#include "usb_stack_config.h"

//#if HID_CONFIG
 
#include "usb_logger.h"


/*****************************************************************************
 * Global Variables
 *****************************************************************************/

/* Declare and initialise the ep_service_array array. This contains pointers to the 
    callback (or service) functions to be executed when a TOK_DNE event occurs for
    an endpoint. */
USB_LOGGER_EP_SERVICE_CALL ep_service_array[ENDPOINT_COUNT] = 
{
	USB_EP1_SERVICE_CALL, /* Address of EP1 Service Call */
	USB_EP2_SERVICE_CALL, /* Address of EP2 Service Call */
	USB_EP3_SERVICE_CALL, /* Address of EP3 Service Call */
	USB_EP4_SERVICE_CALL  /* Address of EP4 Service Call */
}; 


extern USB_ENDPOINTS usb_desc_ep;
extern DESC_CALLBACK_FUNCTIONS_STRUCT  desc_callback;


 LOGGER_DEVICE_STRUCT    *device_array[MAX_LOGGER_DEVICE];          
 
 LOGGER_GLOBAL_VARIABLE_STRUCT g_logger;
 
 /* Control structures for EP1 & EP3 OUT (receive) packet transactions */
 EP_RX_CTRL ep1_rx_ctrl;
 EP_RX_CTRL ep3_rx_ctrl;
 
 uint_8 epCnt =0;
  


/*****************************************************************************
 * Local Functions
 *****************************************************************************/
 /*************************************************************************//*!
 *
 * @name  USB_Logger_Allocate_Handle
 *
 * @brief The funtion reserves entry in device array and returns the index.
 *
 * @param none.
 * @return returns the reserved handle or if no entry found device busy.      
 *
 *****************************************************************************/
static LOGGER_HANDLE  USB_Logger_Allocate_Handle()
{
    uint_32 cnt = 0;
    for (;cnt< MAX_LOGGER_DEVICE;cnt++)
    {
       if (device_array[cnt] == NULL)
        return cnt;
    }
    return USBERR_DEVICE_BUSY;
}


 /*************************************************************************//*!
 *
 * @name  USB_Logger_Get_Device_Ptr
 *
 * @brief The funtion gets the device pointer from device array .
 *
 * @param handle  index in device array.
 * @return returns returns pointer to LOGGER device structure..      
 *
 *****************************************************************************/
static LOGGER_DEVICE_STRUCT_PTR USB_Logger_Get_Device_Ptr(LOGGER_HANDLE handle)
{
     return device_array[handle]; 
}

 /*************************************************************************//*!
 *
 * @name  LOGGER_USB_Map_Ep_To_Struct_Index
 *
 * @brief The funtion maps the endpoint num to the index of the ep data 
 *           structure
 *
 * @param handle          handle to identify the controller
 * @param ep_num          endpoint num
 *
 * @return index          mapped index       
 *
 *****************************************************************************/
static uint_8 LOGGER_USB_Map_Ep_To_Struct_Index(LOGGER_DEVICE_STRUCT_PTR devicePtr,
uint_8 ep_num
) 
{
    uint_8 count = 0;
    
    USB_ENDPOINTS *ep_desc_data = devicePtr->ep_desc_data;
    /* map the endpoint num to the index of the endpoint structure */
    for(count = 0; count < ep_desc_data->count; count++) 
    {
        if(ep_desc_data->ep[count].ep_num == ep_num)
            break;
    }
    
    return count; 
    
}
 

/**************************************************************************//*!
 *
 * @name  USB_Class_LOGGER_Init
 *
 * @brief The funtion initializes the Device and Controller layer 
 *
 * @param void
 *
 * @return status       
 *         USB_OK           : When Successfull 
 *         Others           : Errors
 ******************************************************************************
 *
 *This function initializes the Logger Class layer and layers it is dependent on 
 *
 *****************************************************************************/

LOGGER_HANDLE USB_Class_LOGGER_Init(void)

{
    uint_8 error;
    uint_8 index;
    LOGGER_HANDLE        loggerHandle;
    LOGGER_DEVICE_STRUCT_PTR   devicePtr = NULL;
    

    
    _int_disable();
    
    

        /* Initialize the Logger Global Variable Structure. */
	USB_mem_zero(&g_logger, sizeof(LOGGER_GLOBAL_VARIABLE_STRUCT));

    /*
     * Initialize the USB interface. 
     */
     
    /* Allocate memory for the LOGGER_DEVICE_STRUCT Structure. */
    /* devicePtr will be used as a pointer to this structure. */
        devicePtr = (LOGGER_DEVICE_STRUCT_PTR)USB_mem_alloc_zero(sizeof(LOGGER_DEVICE_STRUCT));
    if (NULL == devicePtr)
    {
        #if _DEBUG
            printf("USB_Class_Logger_Init: Memalloc failed\n");
        #endif  
        return USBERR_ALLOC;
    }
    
    /* Initialise the Logger device structure. */
    devicePtr->ep_desc_data = &usb_desc_ep;   /* Provides info on the number of EPs 
                                                 and their individual Typr, Dir and Packet Size.
                                                 In usb_descriptor.c */
    devicePtr->logger_class_callback.callback =USB_App_Callback;
    devicePtr->logger_endpoint_data.count = devicePtr->ep_desc_data->count; // # EPs
    devicePtr->logger_endpoint_data.ep = g_logger.ep;
    
    for(index = 0; index < usb_desc_ep.count; index++) 
   {            
      devicePtr->logger_endpoint_data.ep[index].endpoint = 
                                 usb_desc_ep.ep[index].ep_num;                                          
      devicePtr->logger_endpoint_data.ep[index].type = 
                                  usb_desc_ep.ep[index].type;
      devicePtr->logger_endpoint_data.ep[index].bin_consumer = 0x00;         
      devicePtr->logger_endpoint_data.ep[index].bin_producer = 0x00;        
    }
      
     /* Save the callback pointer. */
     devicePtr->logger_class_callback.callback = USB_App_Callback;
     devicePtr->logger_class_callback.arg = &g_logger.app_handle;
     
     /* Save the callback pointer. */
     
     /* Save the callback to ask application for class specific params. */
     devicePtr->param_callback.callback = USB_App_Param_Callback;
     devicePtr->param_callback.arg = &g_logger.app_handle;
     
    /*  The system is set up to handle multiple devices 
    	 but in reality will only handle 1.
    	Each device is described by its device struct eg LOGGER_DEVICE_STRUCT.
    	device_array (declared at the start of this file) holds pointers to all
    	 device structures (eg LOGGER_DEVICE_STRUCT_PTR) declared for the 
    	 system (in reality there is only 1.
    	loggerHandle is the index to LOGGER_DEVICE_STRUCT_PTR in device_array. 
    */
    /* Set loggerHandle as an index to the next vacany entry in device_array. */
    loggerHandle = USB_Logger_Allocate_Handle(); 
                                                 
    if (USBERR_DEVICE_BUSY == loggerHandle) 
    {
        USB_mem_free(devicePtr);
        devicePtr = NULL;
        return USBERR_INIT_FAILED;
    }

    /* Save the index to LOGGER_DEVICE_STRUCT_PTR in device_array. */
    devicePtr->user_handle = loggerHandle;
    
    /* Save the index to LOGGER_DEVICE_STRUCT_PTR in device_array.
    	This will be used to get LOGGER_DEVICE_STRUCT_PTR in other 
    	parts of the application.
     */
    g_logger.app_handle = loggerHandle;
    
    /* Save LOGGER_DEVICE_STRUCT_PTR in device_array[loggerHandle]. */
    device_array[loggerHandle] = devicePtr;
    
    
    /* Initialize the device layer.
    * This uses the Device API "_usb_device_init()" from dev_main.c.
    *    See USB Device API Reference MQXUSBDEVAPI.pdf Sect 3.2.6.
    * Creates and initialises USB_DEV_STATE_STRUCT: usbpru.h and 
    *    sets LOGGER_DEVICE_STRUCT_PTR->handle: as a pointer to it.
    */
    
    error = _usb_device_init
    	(
    		DEVICE_NUMBER, 			// Always zero as system only set up for one device
    		&(devicePtr->handle), 	// Will be set to USB_DEV_STATE_STRUCT_PTR
        	(uint_8)(devicePtr->ep_desc_data->count+1)	// Number of endpoints
        );
    
    /* Ignore errors at the moment */
//    if(error != USB_OK)
//    {
//      goto error1;  
//    }

    
   /* Initialize the generic class functions 
   *  Calls USB_Class_Init() in usb_class.c.
   */
   devicePtr->class_handle = USB_Class_Init		// File usb_class.c
   	(
   		devicePtr->handle,			// usb_dev_ptr (Pointer to USB_DEV_STATE_STRUCT)
   		USB_Class_Logger_Event,		// Defined in this file. Loaded in 
   									//   USB_CLASS_OBJECT_STRUCT_PTR->class_callback.
   									// Also loaded in
   									//   USB_CLASS_FW_OBJECT_STRUCT_PTR->
   									//     class_callback.callback.
   		USB_Logger_Other_Requests,	// Defined in this file. Loaded in
   									// USB_CLASS_FW_OBJECT_STRUCT_PTR->
   									//     other_req_callback.callback.  
   		(void *)devicePtr,			// &LOGGER_DEVICE_STRUCT_PTR.
        &desc_callback				// usb_descriptor.c
     );
    /* Ignore errors at the moment */
//   if(error != USB_OK)
//   {
//      goto error2;  
//   }

    
    _int_enable(); 
    
    
}


/**************************************************************************//*!
 *
 * @name  USB_Class_Logger_Event
 *
 * @brief The funtion initializes LOGGER endpoints. 
 *			Function USB_Class_LOGGER_Init() (above) loads the address of this 
 *			function in USB_CLASS_OBJECT_STRUCT_PTR->class_callback.
 * 			This function is called from USB_Reset_Service() in file usb_class.c
 *			as part of servicing a USB reset
 *
 * @param handle          handle to Identify the controller
 * @param event           pointer to event structure
 * @param val             gives the configuration value 
 *
 * @return None       
 *
 *****************************************************************************/
void USB_Class_Logger_Event(uint_8 event, void* val,void * arg) 
{
    uint_8 index;
    
 	
    
    USB_EP_STRUCT_PTR ep_struct_ptr; /* Pointer to an EP structure: devapi.h */
    
    LOGGER_DEVICE_STRUCT_PTR  devicePtr; /* Pointer to LOGGER_DEVICE_STRUCT: usb_logger.h */
    
    devicePtr = (LOGGER_DEVICE_STRUCT_PTR)arg; /* Set devicePtr to point to
                                                   LOGGER_DEVICE_STRUCT */
    
    if(event == USB_APP_ENUM_COMPLETE) 
    {
        uint_8 count = 0;
        uint_8 component;
        
        /* Get the endpoints from the descriptor module. usb_descriptor.c 
           LOGGER_DEVICE_STRUCT.ep_desc_data is set to &usb_desc_ep in USB_Class_LOGGER_Init() (above).
           Declare ep_desc_data as a pointer to a USB_ENDPOINT structure & 
               initialise it to &usb_desc_ep */
        USB_ENDPOINTS *ep_desc_data = devicePtr->ep_desc_data; /* &usb_desc_ep: usb_descriptor.c */
        
        /* Intialize all non-control endpoints */            
        while(count < ep_desc_data->count) 
        {
            /* Initialise the endpoint using the USB Device API "_usb_device_init_endpoint()"
                  See USB Device API Reference MQXUSBDEVAPI.pdf section 3.2.7.
                  Function in file dev_main.c. */
                  
            ep_struct_ptr= (USB_EP_STRUCT*) &ep_desc_data->ep[count]; /* &ep[COUNT]: usb_descriptor.c */
            component = (uint_8)(ep_struct_ptr->ep_num |           /* EP Number */
                (ep_struct_ptr->direction << COMPONENT_PREPARE_SHIFT)); /* Direction */
            /* USB Device API call in dev_main.c */
            /* devicePtr->handle is set to USB_DEV_STATE_STRUCT_PTR: usbprv_fs.h.
               See _usb_device_init(): dev_main.c. */
            (void)_usb_device_init_endpoint(devicePtr->handle, ep_struct_ptr, TRUE);
        
            /* Register callback service for each non-control endpoint.
               Uses the USB Device API "_usb_device_register_service()".
               See USB Device API Reference MQXUSBDEVAPI.pdf section 3.2.10.
                  Function in file dev_main.c. */
            (void)_usb_device_register_service(devicePtr->handle,
                (uint_8)(USB_SERVICE_EP0+ep_struct_ptr->ep_num), 
                ep_service_array[count], arg);
            
            /* Set the EndPoint Status as Idle in the device layer */
            /* (no need to specify direction for this case) */
            /* Uses the USB Device API "_usb_device_set_status()".
               See USB Device API Reference MQXUSBDEVAPI.pdf section 3.2.13.
                  Function in file dev_utl.c. */            
            (void)_usb_device_set_status(devicePtr->handle,
                  (uint_8)(USB_STATUS_ENDPOINT|component),
                  (uint_16)USB_STATUS_IDLE);                                                                                                         
            count++;                                                    
        }   
         
    }
    else if(event == USB_APP_BUS_RESET) 
    {
        /* clear producer and consumer */        
        for(index = 0; index < devicePtr->logger_endpoint_data.count; index++) 
        {                  
            devicePtr->logger_endpoint_data.ep[index].bin_consumer = 0x00;         
            devicePtr->logger_endpoint_data.ep[index].bin_producer = 0x00;        
        }
    }
        
    if(devicePtr->logger_class_callback.callback != NULL)
    {
        devicePtr->logger_class_callback.callback(event,val,devicePtr->logger_class_callback.arg);
    }
    
}



/**************************************************************************//*!
 *
 * @name  USB_Class_EP2_Send_Data
 *
 * @brief : Initiates transmission of a packet via EP2.
 *
 * @param ep_num          :   endpoint num 
 * @param app_buff        :   start address of the buffer to send
 * @param size            :   number of bytes in the packet   
 *
 * @return status       
 *         USB_OK           	: When Successfull 
 *         USBERR_DEVICE_BUSY   : Errors - queue full.
 *****************************************************************************/
uint_8 USB_Class_EP2_Send_Data(
                                uint_8 ep_num,/*[IN]*/
                                uint_8_ptr app_buff,/*[IN]*/
                                uint_32 size /*[IN]*/
                               ) 
{
    uint_8 index;
    uint_8 producer, consumer;
    uint_8 error = USB_OK;
    LOGGER_DEVICE_STRUCT_PTR  devicePtr;
    USB_ENDPOINTS *ep_desc_data;
       
        
    /* Need to set devicePtr to &LOGGER_DEVICE_STRUCT which is stored at
    	device_array[g_logger.app_handle]. see USB_Class_LOGGER_Init(). */
    devicePtr = USB_Logger_Get_Device_Ptr(g_logger.app_handle);
    
    /* Map the endpoint num to the index of the endpoint structure.
    	The EP structure is usb_desc_ep in file USB_descriptor.c.
     */
    index = LOGGER_USB_Map_Ep_To_Struct_Index(devicePtr, ep_num);
    
    ep_desc_data = devicePtr->ep_desc_data; 
    
    /* The Logger packet queue is a fifo queue can hold 4 packets. 
    	The queue is controlled with two pointers, both are deceared as uint_8: 
    		producer - used to calculate the pointer to where the next packet is placed
    					in the queue.
    		consumer - used to calculate the pointer to the next packet to be removed from
    					the queue.
    */
    producer = devicePtr->logger_endpoint_data.ep[index].bin_producer;
    consumer = devicePtr->logger_endpoint_data.ep[index].bin_consumer;

    /* The queue is empty when producer = consumer, 
    	and full when producer - consumer = 4. */
    if((uint_8)(producer - consumer) != (uint_8)(LOGGER_MAX_QUEUE_ELEMS))  
    {/* The bin is not full*/
    
        uint_8 queue_num = (uint_8)(producer % LOGGER_MAX_QUEUE_ELEMS);
        /* Put all send request parameters in the endpoint data structure */
        	/* The endpoint the packet is to be sent via. */
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].channel = ep_num;
        	/* The buffer where the packet is saved. */
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].app_buff = app_buff;
        	/* Packet size. */
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].size = size;
        	/* &USB_DEV_STATE_STRUCT */ 
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].handle = devicePtr->handle;
   
        /* Increment producer */       
        devicePtr->logger_endpoint_data.ep[index].bin_producer++;
        producer++;
             
        if((uint_8)(producer - consumer) == (uint_8)1)         
        {   
            /* Initiate transmission if there is only one packet in the queue.
            	Other packets placed in the queue will be transmitted by
            	USB_EP2_SERVICE_CALL which is called in response to a TOK_DNE
            	interrupt on EP2. 
             */          
            error = USB_Class_Send_Data(devicePtr->class_handle, ep_num, app_buff, size);
        }        
    }
    else /* Bin is full */
    {
        error = USBERR_DEVICE_BUSY; 
    }
    
    return error;
}



/**************************************************************************//*!
 *
 * @name  USB_Class_EP4_Send_Data
 *
 * @brief : Initiates transmission of packets via EP4.
 *
 * @param ep_num          :   endpoint num 
 * @param app_buff        :   start address of the buffer to send
 * @param size            :   number of bytes in the packet   
 *
 * @return status       
 *         USB_OK           	: When Successfull 
 *         USBERR_DEVICE_BUSY   : Errors - queue full.
 *****************************************************************************/
uint_8 USB_Class_EP4_Send_Data(
                                uint_8 ep_num,/*[IN]*/
                                uint_8_ptr app_buff,/*[IN]*/
                                uint_32 size /*[IN]*/
                               ) 
{
    uint_8 index;
    uint_8 producer, consumer;
    uint_8 error = USB_OK;
    LOGGER_DEVICE_STRUCT_PTR  devicePtr;
    USB_ENDPOINTS *ep_desc_data;
       
        
    /* Need to set devicePtr to &LOGGER_DEVICE_STRUCT which is stored at
    	device_array[g_logger.app_handle]. see USB_Class_LOGGER_Init(). */
    devicePtr = USB_Logger_Get_Device_Ptr(g_logger.app_handle);
    
    /* Map the endpoint num to the index of the endpoint structure.
    	The EP structure is usb_desc_ep in file USB_descriptor.c.
    */
    index = LOGGER_USB_Map_Ep_To_Struct_Index(devicePtr, ep_num);
    
    ep_desc_data = devicePtr->ep_desc_data; 
    
    /* The Logger packet queue is a fifo queue can hold 4 packets. 
    	The queue is controlled with two pointers, both are deceared as uint_8: 
    		producer - used to calculate the pointer to where the next packet is placed
    					in the queue.
    		consumer - used to calculate the pointer to the next packet to be removed from
    					the queue.
    */
    producer = devicePtr->logger_endpoint_data.ep[index].bin_producer;
    consumer = devicePtr->logger_endpoint_data.ep[index].bin_consumer;

    /* The queue is empty when producer = consumer, 
    	and full when producer - consumer = 4. */
    if((uint_8)(producer - consumer) != (uint_8)(LOGGER_MAX_QUEUE_ELEMS))  
    {/* The bin is not full*/
    
        uint_8 queue_num = (uint_8)(producer % LOGGER_MAX_QUEUE_ELEMS);
        /* Put all send request parameters in the endpoint data structure */
        	/* The endpoint the packet is to be sent via. */
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].channel = ep_num;
        	/* The buffer where the packet is saved. */
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].app_buff = app_buff;
        	/* Packet size. */
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].size = size;
        	/* &USB_DEV_STATE_STRUCT */ 
        devicePtr->logger_endpoint_data.ep[index].queue[queue_num].handle = devicePtr->handle;
   
        /* Increment producer */       
        devicePtr->logger_endpoint_data.ep[index].bin_producer++;
        producer++;
             
        if((uint_8)(producer - consumer) == (uint_8)1)         
        {   
            /* Initiate transmission if there is only one packet in the queue.
            	Other packets placed in the queue will be transmitted by
            	USB_EP2_SERVICE_CALL which is called in response to a TOK_DNE
            	interrupt on EP2. 
             */          
            error = USB_Class_Send_Data(devicePtr->class_handle, ep_num, app_buff, size);
        }        
    }
    else /* Bin is full */
    {
        error = USBERR_DEVICE_BUSY; 
    }
    
    return error;
}
/***************************************************************************
 *
 * @name  USB_EP1_SERVICE_CALL
 *
 * @brief 	A data packet has arrived at EP1 and a TOK_DNE interrupt event
 *				has been generated.
 *			This is the callback function (interrupt service routine) 
 *         		for this event EP1. 
 *			Called from _usb_device_call_service() - file dev_main.c.
 *
 *			Structure ep1_rx_ctrl is used as a status register for receiving
 *				packets on EP1. It is updated.
 *
 * @param event           Pointer to a USB_EVENT_STRUCT (devapi.h) for EP1
 * @param arg             Pointer to the LOGGER_DEVICE_STRUCT (usb_logger.h)
 *
 * @return None       
 *
 *****************************************************************************/
void USB_EP1_SERVICE_CALL(PTR_USB_EVENT_STRUCT event, pointer arg)
{
    LOGGER_DEVICE_STRUCT_PTR  devicePtr;
    USB_DEV_STATE_STRUCT_PTR  usb_dev_ptr;
 	EP_RX_CTRL_PTR ep1ctrlPtr;			// EP1 control & buffer structure pointer
 	uint_8_ptr buff_ptr;		// Pointer to the BD receive data buffer.
 	uint_8 ep_num = 1;			// Endpoint number
    
    devicePtr = (LOGGER_DEVICE_STRUCT_PTR)arg;
    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)devicePtr->handle;
    
 	ep1ctrlPtr = &ep1_rx_ctrl;		// Set the pointer to the EP1 control structure

	/* A new EP1 OUT packet has arrived. Set the control structure */
	/* First check the previous packet has been transferred to the application */
	if(ep1ctrlPtr->pkt_rec)
	{
		ep1ctrlPtr->overrun_err = TRUE;  // Packet not transferred.
		                                 // Generate an overrun error.
	}
	
//	epCnt += 1;

	/* Set EP1 control & buffer structure */
    ep1ctrlPtr->buffer_ptr = event->buffer_ptr;	// pointer to the received packet
    ep1ctrlPtr->len = event->len;				// # bytes in the packet
 	ep1ctrlPtr->pkt_rec = TRUE;					// Set packet received flag
 	
// 	if(epCnt == 4)
// 	{
// 		epCnt = 0;
// 	}
 	
 	
 	/* 
 	Set up an XD struct for the next EP1 OUT transaction 
 	*/
 	/* Set receive data buffer address */
	if(usb_dev_ptr->EP_INFO[ep_num].rx_buf_odd)	// 
		{
			buff_ptr = usb_dev_ptr->EP_INFO[ep_num].data_buffer + USB_EP_PKT_SIZE;
		}
		else
		{
			buff_ptr = usb_dev_ptr->EP_INFO[ep_num].data_buffer;
		}
 	/* Set up the XD_STRUCT */
 	_usb_device_recv_data(usb_dev_ptr, ep_num, buff_ptr, USB_EP_PKT_SIZE);
 	
 	
}

/***************************************************************************
 *
 * @name  USB_EP2_SERVICE_CALL
 *
 * @brief 		This is the Callback function to be executed following a 
 *					TOK_DNE event on EP2.
 *				This function is called because a data packet has been 
 *					transmitted from EP2. It will check if further data
 *					packets are ready to send and if so it will send the
 *					next one from the queue.
 *				Note: data transmission is NOT iniated here. To initiate
 *					transmission of a packet see USB_Class_EP2_Send_Data().
 *
 * @param event           Pointer to a USB_EVENT_STRUCT for EP2
 * @param arg             Pointer to the LOGGER_DEVICE_STRUCT
 *
 * @return None       
 *
 *****************************************************************************/
void USB_EP2_SERVICE_CALL(PTR_USB_EVENT_STRUCT event, pointer arg)
{
    uint_8 index;
    uint_8 producer, consumer;
    LOGGER_DEVICE_STRUCT_PTR  devicePtr;
    USB_ENDPOINTS *ep_desc_data;
    
    devicePtr = (LOGGER_DEVICE_STRUCT_PTR)arg;
    
    ep_desc_data = devicePtr->ep_desc_data; 

     /* map the endpoint num to the index of the endpoint structure */
    index = LOGGER_USB_Map_Ep_To_Struct_Index(devicePtr, event->ep_num); 
                                               
    producer = devicePtr->logger_endpoint_data.ep[index].bin_producer;    
        
    /* if there are no errors de-queue the queue and decrement the no. of 
     transfers left, else send the same data again. NOT done here. */
     /* de-queue if the send is complete with no error */
   devicePtr->logger_endpoint_data.ep[index].bin_consumer++;  
        
    consumer = devicePtr->logger_endpoint_data.ep[index].bin_consumer;
        
    if(consumer != producer) 
    {/*if bin is not empty */
        
        USB_CLASS_LOGGER_QUEUE queue;    
        /* send the next packet in queue */                
        queue = devicePtr->logger_endpoint_data.ep[index].
                                         queue[consumer % LOGGER_MAX_QUEUE_ELEMS];
                        
        (void)USB_Class_Send_Data(devicePtr->class_handle, queue.channel, 
                                      queue.app_buff, queue.size);                                                                                                
    }        
    
    /* notify the app of the send complete. NOT used here */
    devicePtr->logger_class_callback.callback(USB_APP_SEND_COMPLETE, 0,
    devicePtr->logger_class_callback.arg); 
}


/***************************************************************************
 *
 * @name  USB_EP3_SERVICE_CALL
 *
 * @brief 	A data packet has arrived at EP3 and a TOK_DNE interrupt event
 *				has been generated.
 *			This is the callback function (interrupt service routine) 
 *         		for this event EP3. 
 *			Called from _usb_device_call_service() - file dev_main.c.
 *
 *			Structure ep3_rx_ctrl is used as a status register for receiving
 *				packets on EP1. It is updated.
 *
 * @param event           Pointer to a USB_EVENT_STRUCT for EP3
 * @param arg             Pointer to the LOGGER_DEVICE_STRUCT
 *
 * @return None       
 *
 *****************************************************************************/
void USB_EP3_SERVICE_CALL(PTR_USB_EVENT_STRUCT event, pointer arg)
{
    LOGGER_DEVICE_STRUCT_PTR  devicePtr;
    USB_DEV_STATE_STRUCT_PTR  usb_dev_ptr;
 	EP_RX_CTRL_PTR ep3ctrlPtr;			// EP3 control & buffer structure pointer
 	uint_8_ptr buff_ptr;		// Pointer to the BD receive data buffer.
 	uint_8 ep_num = 3;			// Endpoint number
    
    devicePtr = (LOGGER_DEVICE_STRUCT_PTR)arg;
    usb_dev_ptr = (USB_DEV_STATE_STRUCT_PTR)devicePtr->handle;
    
 	ep3ctrlPtr = &ep3_rx_ctrl;		// Set the pointer to the EP3 control structure

	/* A new EP3 OUT packet has arrived. Set the control structure */
	/* First check the previous packet has been transferred to the application */
	if(ep3ctrlPtr->pkt_rec)
	{
		ep3ctrlPtr->overrun_err = TRUE;  // Packet not transferred.
		                                 // Generate an overrun error.
	}
	epCnt += 1;
	/* Set EP3 control & buffer structure */
    ep3ctrlPtr->buffer_ptr = event->buffer_ptr;	// pointer to the received packet
    ep3ctrlPtr->len = event->len;		// # bytes in the packet
 	ep3ctrlPtr->pkt_rec = TRUE;			// Set packet received flag
 	
 	if(epCnt == 4)
 	{
 		epCnt = 0;
 	}
 	
 	
 	/* 
 	Set up an XD struct for the next EP3 OUT transaction 
 	*/
 	/* Set receive data buffer address */
	if(usb_dev_ptr->EP_INFO[ep_num].rx_buf_odd)	// 
		{
			buff_ptr = usb_dev_ptr->EP_INFO[ep_num].data_buffer + USB_EP_PKT_SIZE;
		}
		else
		{
			buff_ptr = usb_dev_ptr->EP_INFO[ep_num].data_buffer;
		}
 	/* Set up the XD_STRUCT */
 	_usb_device_recv_data(usb_dev_ptr, ep_num, buff_ptr, USB_EP_PKT_SIZE);
	
	
}


/***************************************************************************
 *
 * @name  USB_EP4_SERVICE_CALL
 *
 * @brief 		This is the Callback function to be executed following a 
 *					TOK_DNE event on EP4.
 *				This function is called because a data packet has been 
 *					transmitted from EP4. It will check if further data
 *					packets are ready to send and if so it will send the
 *					next one from the queue.
 *				Note: data transmission is NOT iniated here. To initiate
 *					transmission of a packet see USB_Class_EP4_Send_Data().
 *
 * @param event           Pointer to a USB_EVENT_STRUCT for EP4
 * @param arg             Pointer to the LOGGER_DEVICE_STRUCT
 *
 * @return None       
 *
 *****************************************************************************/
void USB_EP4_SERVICE_CALL(PTR_USB_EVENT_STRUCT event, pointer arg)
{
    uint_8 index;
    uint_8 producer, consumer;
    LOGGER_DEVICE_STRUCT_PTR  devicePtr;
    USB_ENDPOINTS *ep_desc_data;
    
    devicePtr = (LOGGER_DEVICE_STRUCT_PTR)arg;
    
    ep_desc_data = devicePtr->ep_desc_data; 

     /* map the endpoint num to the index of the endpoint structure */
    index = LOGGER_USB_Map_Ep_To_Struct_Index(devicePtr, event->ep_num); 
                                               
    producer = devicePtr->logger_endpoint_data.ep[index].bin_producer;    
        
    /* if there are no errors de-queue the queue and decrement the no. of 
     transfers left, else send the same data again. NOT done here. */
     /* de-queue if the send is complete with no error */
   devicePtr->logger_endpoint_data.ep[index].bin_consumer++;  
        
    consumer = devicePtr->logger_endpoint_data.ep[index].bin_consumer;
        
    if(consumer != producer) 
    {/*if bin is not empty */
        
        USB_CLASS_LOGGER_QUEUE queue;    
        /* send the next packet in queue */                
        queue = devicePtr->logger_endpoint_data.ep[index].
                                         queue[consumer % LOGGER_MAX_QUEUE_ELEMS];
                        
        (void)USB_Class_Send_Data(devicePtr->class_handle, queue.channel, 
                                      queue.app_buff, queue.size);                                                                                                
    }        
    
    /* notify the app of the send complete. NOT used here */
    devicePtr->logger_class_callback.callback(USB_APP_SEND_COMPLETE, 0,
    devicePtr->logger_class_callback.arg); 	
}


/**************************************************************************//*!
 *
 * @name  USB_Logger_Other_Requests
 *
 * @brief The funtion provides flexibilty to add class and vendor specific
 *        requests 
 *
 * @param handle:
 * @param setup_packet:     setup packet recieved      
 * @param data:             data to be send back
 * @param size:             size to be returned    
 *
 * @return status:       
 *                        USB_OK : When Successfull       
 *                        Others : When Error
 *
 *****************************************************************************/
uint_8 USB_Logger_Other_Requests(USB_SETUP_STRUCT * setup_packet, 
                          uint_8_ptr *data, 
                          uint_32 *size,
                          pointer arg) 
{    
 //   UNUSED_ARGUMENT (arg)
 //   UNUSED_ARGUMENT (size)
 //   UNUSED_ARGUMENT (data)
 //   UNUSED_ARGUMENT (setup_packet)
     
    uint_8 num = 0;
    
    num += 1;
    
	

}


/******************************************************************************
 * 
 *    @name        USB_App_Param_Callback
 *    
 *    @brief       This function handles the callback for Get/Set report req  
 *                  
 *    @param       request  :  request type
 *    @param       value    :  give report type and id
 *    @param       data     :  pointer to the data 
 *    @param       size     :  size of the transfer
 *
 *    @return      status
 *                  USB_OK  :  if successful
 *                  else return error
 *
 *****************************************************************************/
 uint_8 USB_App_Param_Callback
 (
 	uint_8 request, 
 	uint_16 value, 
 	uint_8_ptr* data, 
    uint_32* size,
    pointer arg
) 
{
 //   UNUSED_ARGUMENT (request)
 //   UNUSED_ARGUMENT (value)
 //   UNUSED_ARGUMENT (data)
 //   UNUSED_ARGUMENT (size)
 //   UNUSED_ARGUMENT (arg)


 return;
}  

/******************************************************************************
 * 
 *    @name        USB_App_Callback
 *    
 *    @brief       This function handles the callback  
 *                  
 *    @param       handle : handle to Identify the controller
 *    @param       event_type : value of the event
 *    @param       val : gives the configuration value 
 * 
 *    @return      None
 *
 *****************************************************************************/
void USB_App_Callback(uint_8 event_type, void* val,pointer arg) 
{    
    UNUSED_ARGUMENT (arg)
    UNUSED_ARGUMENT (val)
    
    switch(event_type)
    {
    	case USB_APP_BUS_RESET:     
    	    g_logger.logger_init=FALSE;
        	break;
		case USB_APP_ENUM_COMPLETE:    
        	g_logger.logger_init = TRUE;         
 //       	move_mouse();/* run the coursor movement code */
        	break;
    	case USB_APP_SEND_COMPLETE:    
	    	 /*check whether enumeration is complete or not */
	    	if(g_logger.logger_init)
	        {
				#if COMPLIANCE_TESTING	           
	            	uint_32 g_compliance_delay = 0x009FFFFF;
	        		while(g_compliance_delay--);
	        	#endif
//	            move_mouse();/* run the coursor movement code */                  
	        }
	        break;
    	case USB_APP_ERROR: 
    		/* user may add code here for error handling 
    		   NOTE : val has the value of error from h/w*/
    		break;
		default: 
			break;    		
    }	
    return;
}

